package com.unswift.cloud.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiConstructor;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.JsonUtils;
import com.unswift.utils.ObjectUtils;

/**
 * http请求公共操作bean
 * @author unswift
 *
 */
@Component
@Api(value="Http公共操作类", author="unswift", date="2023-04-16", version="1.0.0")
public class HttpUtils {

	@Autowired
	@ApiField("Http请求客户端")
	private HttpClient httpClient;
	
	@ApiField("http编码")
	@Value("${http-client.connection.charset}")
	private String charset;
	
	@ApiMethod(value="get请求返回字符串", params=@ApiField("请求的url"), returns=@ApiField("请求返回的内容"))
	public String getToString(String url){
		return getToString(url, null);
	}
	
	@ApiMethod(value="get请求返回字符串", params={@ApiField("请求的url"), @ApiField("请求header")}, returns=@ApiField("请求返回的内容"))
	public String getToString(String url, Map<String, String> header){
		try {
			HttpGet httpGet=new HttpGet(url);
			httpGet.addHeader("content-type", "application/json;charset=utf-8");
			if(ObjectUtils.isNotEmpty(header)){
				for (Map.Entry<String, String> entry : header.entrySet()) {
					httpGet.addHeader(entry.getKey(), entry.getValue());
				}
			}
			HttpResponse response=httpClient.execute(httpGet);
			return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("http.execute.exception", e, url, e.getMessage());
		}
	}
	
	@ApiMethod(value="get请求返回byte数组", params={@ApiField("请求的url")}, returns=@ApiField("请求返回的内容"))
	public byte[] getToByte(String url){
		return getToByte(url, null);
	}
	
	@ApiMethod(value="get请求返回byte数组", params={@ApiField("请求的url"), @ApiField("请求header")}, returns=@ApiField("请求返回的内容"))
	public byte[] getToByte(String url, Map<String, String> header){
		try {
			HttpGet httpGet=new HttpGet(url);
			httpGet.addHeader("content-type", "application/octet-stream");
			if(ObjectUtils.isNotEmpty(header)){
				for (Map.Entry<String, String> entry : header.entrySet()) {
					httpGet.addHeader(entry.getKey(), entry.getValue());
				}
			}
			HttpResponse response=httpClient.execute(httpGet);
			InputStream stream=response.getEntity().getContent();
			ByteArrayOutputStream output=new ByteArrayOutputStream();
			byte[] buff=new byte[1024*10];
			int length;
			while((length=stream.read(buff))>0){
				output.write(buff, 0, length);
			}
			return output.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("http.execute.exception", e, url, e.getMessage());
		}
	}
	
	@ApiMethod(value="post请求返回字符串", params={@ApiField("请求的url"), @ApiField("请求参数")}, returns=@ApiField("请求返回的内容"))
	public String postToString(String url, Map<String, Object> params){
		return postToString(url, params, null);
	}
	
	@ApiMethod(value="post请求返回字符串", params={@ApiField("请求的url"), @ApiField("请求参数"), @ApiField("请求Header")}, returns=@ApiField("请求返回的内容"))
	public String postToString(String url, Map<String, Object> params, Map<String, String> header){
		try {
			HttpPost httpPost=new HttpPost(url);
			httpPost.addHeader("content-type", "application/json;charset=utf-8");
			if(ObjectUtils.isNotEmpty(header)){
				for (Map.Entry<String, String> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			List<NameValuePair> values = new ArrayList<NameValuePair>();
			if(ObjectUtils.isNotEmpty(params)){
				for (Map.Entry<String, Object> entry : params.entrySet()) {
					if(ObjectUtils.isNotEmpty(entry.getValue())){
						BasicNameValuePair param = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());
						values.add(param);
					}
				}
			}
			httpPost.setEntity(new UrlEncodedFormEntity(values, charset));
			HttpResponse response=httpClient.execute(httpPost);
			return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("http.execute.exception", e, url, e.getMessage());
		}
	}
	
	@ApiMethod(value="post请求返回字符串", params={@ApiField("请求的url"), @ApiField("请求body对象")}, returns=@ApiField("请求返回的内容"))
	public String postBodyToString(String url, Object body){
		return postBodyToString(url, body, null);
	}
	
	@ApiMethod(value="post请求返回字符串", params={@ApiField("请求的url"), @ApiField("请求body对象"), @ApiField("请求Header")}, returns=@ApiField("请求返回的内容"))
	public String postBodyToString(String url, Object body, Map<String, String> header){
		try {
			HttpPost httpPost=new HttpPost(url);
			httpPost.addHeader("content-type", "application/json;charset=utf-8");
			if(ObjectUtils.isNotEmpty(header)){
				for (Map.Entry<String, String> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			httpPost.setEntity(new StringEntity(JsonUtils.toJson(body), charset));
			HttpResponse response=httpClient.execute(httpPost);
			return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("http.execute.exception", e, url, e.getMessage());
		}
	}
	
	@ApiMethod(value="post上传文件返回字符串", params={@ApiField("请求的url"), @ApiField("请求参数对象"), @ApiField("请求Header")}, returns=@ApiField("请求返回的内容"))
	public String postFileToString(String url, Map<String, Object> params, Map<String, String> header){
		try {
			HttpPost httpPost=new HttpPost(url);
			if(ObjectUtils.isNotEmpty(header)){
				for (Map.Entry<String, String> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
			builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				String key = entry.getKey();
				Object value = params.get(key);
				addMultipartBody(builder, key, value);
			}
			httpPost.setEntity(builder.build());
			HttpResponse response=httpClient.execute(httpPost);
			return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("http.execute.exception", e, url, e.getMessage());
		}
	}
	
	@ApiMethod(value="附件上传设置属性", params={@ApiField("附件实体工厂"), @ApiField("实体键"), @ApiField("实体值")})
	private static void addMultipartBody(MultipartEntityBuilder builder, String key, Object value) throws Exception {
		if (value == null) {
			return;
		}
		if (value instanceof MultipartFile) {
			MultipartFile file = (MultipartFile) value;
			builder.addBinaryBody(key, file.getInputStream(), ContentType.MULTIPART_FORM_DATA,
					file.getOriginalFilename());
		} else if (value instanceof File) {
			File file = (File) value;
			builder.addBinaryBody(key, file, ContentType.MULTIPART_FORM_DATA, file.getName());
		} else if(value instanceof UploadAffix){
			UploadAffix affix=(UploadAffix)value;
			builder.addBinaryBody(key, affix.getAffixStream(), ContentType.DEFAULT_BINARY,
					encode(affix.getAffixName()));
		} else {
			builder.addTextBody(key, value.toString());
		}
	}
	
	@ApiMethod(value="url参数进行编码", params=@ApiField("需要转码的字符串"), returns=@ApiField("转码后字符串"))
	public static String encode(String source){
		try {
			return URLEncoder.encode(source, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("url.encode.exception", e, source, e.getMessage());
		}
	}
	
	@ApiMethod(value="url参数进行解码", params=@ApiField("需要解码的字符串"), returns=@ApiField("解码后字符串"))
	public static String decode(String source){
		try {
			return URLDecoder.decode(source, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("url.decode", e, source, e.getMessage());
		}
	}
	
	@Api(value="上传附件实体", author="unswift", date="2023-07-12", version="1.0.0")
	public static class UploadAffix{
		
		@ApiField("附件名称")
		private String affixName;
		
		@ApiField("附件输入流")
		private InputStream affixStream;
		

		@ApiConstructor(value="附件实体构造函数", params={@ApiField("附件名称"), @ApiField("附件输入流")})
		public UploadAffix(String affixName, InputStream affixStream) {
			super();
			this.affixName = affixName;
			this.affixStream = affixStream;
		}

		public String getAffixName() {
			return affixName;
		}

		public void setAffixName(String affixName) {
			this.affixName = affixName;
		}

		public InputStream getAffixStream() {
			return affixStream;
		}

		public void setAffixStream(InputStream affixStream) {
			this.affixStream = affixStream;
		}

	}
}
